<template>
	<view :class="[classType,'upload_File'] " :style="boxStyle" @click="uploadFile" @longpress="longpressFn">
		<!-- 上传按钮 -->
		<image v-if="!srcCopy&&classType=='default'" class="addIMageDefault" :key="1" :style="addIMageStyle"
			src="./image/addImage4.png" mode="widthFix"></image>
		<image v-if="!srcCopy&&(classType=='iconAndText'||classType=='icon')" class="addIMageIconAndText" :key="2"
			:style="addIMageStyle" src="./image/addImage5.png" mode="widthFix"></image>
		<view class="hint" v-if="!srcCopy&&classType=='iconAndText'" :key="3">
			{{hint}}
		</view>
		<!-- 删除图片的图标 -->
		<image @click.stop="deleteFn()" v-if="srcCopy&&isShowFile&&type=='image'" :key="4" src="./image/remove6.png"
			class="remove" mode="widthFix"></image>

		<view class="ckeckIcon" v-if="srcCopy&&isShowFile&&type=='image'&&isShowCheck">
			<image style="width: 100%;height: 100%;" src="./image/exchange.png" mode="aspectFit"></image>

		</view>
		<!-- 图片 -->
		<image @click.stop="imageClick" class="image" :key="5" v-if="srcCopy&&isShowFile&&type=='image'" :src="srcCopy"
			mode="aspectFill">
		</image>
		<!-- 视频 -->
		<video v-if="srcCopy&&isShowFile&&type=='video'" :style="boxStyle" :key="6" class="image" :src="srcCopy"
			:autoplay="true">
			<cover-image @click.stop="deleteFn()" :key="7" v-if="srcCopy&&isShowFile&&type=='video'" mode='widthFix'
				src="./image/remove6.png" class="removeVideo"></cover-image>
		</video>
		<!-- 裁剪 -->
		<view class="CutBox" v-show="isShowCutArea" @click.stop="CutBoxStop">
			<view class="affirm" @click.stop="affirmBtn">
				确认
			</view>
			<view class="cancal" @click.stop="cancelBtn">
				取消
			</view>
			<canvas @click.stop="fnStop" :style="canvasStyle" :disable-scroll="true" @touchstart.stop="canvasTouchstart"
				@touchend.stop="canvasTouchend" @touchmove.stop="canvasTouchmove" @touchcancel.stop="canvasTouchcancel"
				:canvas-id="id" class="canvas" :id="id"></canvas>
		</view>
	</view>
</template>

<script>
	import updateFile from "./js/updateFile.js"
	export default {
		name: "upload_file",
		props: {
			_id: {
				type: String,
				default: ""
			},
			width: {
				type: Number,
				default: 350,
			},
			height: {
				type: Number,
				default: 350,
			},
			addIconSize: {
				type: Number,
				default: 56, //图标大小
			},
			multiNumber: { //最多上传的个数
				type: Number,
				default: 1,
			},
			// 附带的信息 会在$emit中返回，用于区分页面中多个上传组件，使用同一个回调函数，所产生的回调值
			addition: {},
			// 是否压缩
			isCompress: {
				type: Boolean,
				default: false
			},
			// 压缩率
			quality: {
				type: Number,
				default: 20,
			},
			// 类型
			type: {
				type: String,
				default: "image" //image video 
			},
			// 样式类别
			classType: {
				type: String,
				default: "default" //default icon iconAndText
			},
			// 提示语
			hint: {
				type: String,
				default: "请上传照片" //default icon iconAndText
			},
			// 是否显示上传的文件（如果上传多张，只显示第一张）
			isShowFile: {
				type: Boolean,
				default: true
			},
			// 默认图
			src: {
				type: String,
				default: ""
			},
			// 是否裁剪，只在图片时生效
			isCut: {
				type: Boolean,
				default: true
			},
			// 是否显示选中标识
			isShowCheck: {
				type: Boolean,
				default: false
			},
			// 上传路径
			uploadUrl: {
				type: String,
				default: ""
			},
			// uni.upuploadFile上传所需的name
			name: {
				type: String,
				default: "file"
			},
			// uni.upuploadFile上传所需的请求头
			uploadheader: {
				type: Object,
				default: () => {
					return {}
				}
			}
		},
		data() {
			return {
				boxStyle: {},
				srcCopy: "",
				isShowCutArea: false,
				id: "",
				addIMageStyle: {

				},
				canvasStyle: {

				},
				canvasObj: null,
				imageDrawInfo: {
					imageX: 0, //图片截取的起始点
					imageY: 0, ////图片截取的起始点
					beginningImageX: 0, //图片最初截取的起始点
					beginningImageY: 0, //图片最初截取的起始点
					imageDrawW: 0,
					imageDrawH: 0,
					canvasDrawW: 0,
					canvasDrawH: 0,
					beginningImageDrawW: 0,
					beginningImageDrawH: 0,
				},
				imageW: 0, //图片本身宽度
				imageH: 0, //图片本身高度
				canvasW: 0, //canvas本身宽度
				canvasH: 0, //canvas本身高度
				TouchstartArr: [], //触摸开始的触点数组
				sysInfo: {}, //设备信息
			};
		},

		watch: {
			src() {
				this.srcCopy = this.src
			}
		},
		methods: {
			fnStop() {},
			longpressFn() {
				this.$emit("longpress", this.addition)
			},
			cancelBtn() {
				this.isShowCutArea = false
			},
			affirmBtn() {
				this.isShowCutArea = false
				if (this.imageDrawInfo.imageX == this.imageDrawInfo.beginningImageX &&
					this.imageDrawInfo.imageY == this.imageDrawInfo.beginningImageY &&
					this.imageDrawInfo.beginningImageDrawW == this.imageDrawInfo.imageDrawW &&
					this.imageDrawInfo.beginningImageDrawH == this.imageDrawInfo.imageDrawH) {
					// 图片没有任何移动放大，所以不裁剪
					return
				}
				let self = this
				uni.showLoading({
					title: "图片处理中"
				})
				uni.canvasToTempFilePath({
					x: 0,
					y: 0,
					width: this.canvasW,
					height: this.canvasH,
					destWidth: this.canvasW * 2,
					destHeight: this.canvasH * 2,
					canvasId: this.id,
					success: async function(res) {
						// 在H5平台下，tempFilePath 为 base64
						// console.log(res.tempFilePath)
						// uni.previewImage({
						// 	urls:[res.tempFilePath]
						// })
						try {
							let xhr = await updateFile(res.tempFilePath, this.uploadUrl, this.name, this
								.uploadheader)
							if (xhr.success) {
								uni.hideLoading()
								self.srcCopy = xhr.url
								self.$emit("succeed", {
									url: xhr.url,
									addition: self.addition
								})
							} else {
								uni.showToast({
									title: "图片裁剪失败",
									icon: "none"
								})
								uni.hideLoading()
							}
						} catch (e) {
							uni.showToast({
								title: "图片裁剪失败",
								icon: "none"
							})
						}
					},

					fail() {
						uni.hideLoading()
						self.isShowCutArea = false
						uni.showToast({
							title: "图片裁剪失败",
							icon: "none"
						})
					}
				})

			},
			CutBoxStop() {
				this.isShowCutArea = false
			},
			// 触摸被打断
			canvasTouchcancel(e) {
				this.TouchstartArr = this.TouchstartArr.filter(function(item) {
					item.identifier != e.identifier
				})
			},
			// 触摸开始
			canvasTouchstart(e) {
				// console.log(e, "触摸开始")
				this.TouchstartArr.push(e.changedTouches[0])
			},
			// 触摸后移动
			canvasTouchmove(e) {
				// 单点触摸移动位置
				if (this.imageW != 0 && this.imageH != 0 && this
					.TouchstartArr.length != 0 && e.changedTouches.length == 1 && e.changedTouches[0]
					.identifier == this
					.TouchstartArr[0].identifier) {
					let XL = this.TouchstartArr[0].x - e.changedTouches[0].x //x轴移动的距离
					let YL = this.TouchstartArr[0].y - e.changedTouches[0].y //y轴移动的距离
					for (let i = 0; i < this.TouchstartArr.length; i++) {
						if (this.TouchstartArr[i].identifier == e.changedTouches[0]
							.identifier) {
							this.TouchstartArr[i] = e.changedTouches[0]
						}
					}
					// let newImageX = this.imageDrawInfo.imageX + XL / this.sysInfo.pixelRatio
					// let newImageY = this.imageDrawInfo.imageY + YL / this.sysInfo.pixelRatio
					let newImageX = this.imageDrawInfo.imageX + XL
					let newImageY = this.imageDrawInfo.imageY + YL
					if (newImageX >= 0 && newImageX <= this.imageW - this.imageDrawInfo.imageDrawW) {
						this.imageDrawInfo.imageX = newImageX
					}
					if (newImageY >= 0 && newImageY < this.imageH - this.imageDrawInfo.imageDrawH) {
						this.imageDrawInfo.imageY = newImageY
					}


					this.canvasObj.drawImage(this.srcCopy, this.imageDrawInfo.imageX, this.imageDrawInfo.imageY,
						this
						.imageDrawInfo.imageDrawW, this.imageDrawInfo.imageDrawH, 0, 0, this.imageDrawInfo
						.canvasDrawW,
						this.imageDrawInfo
						.canvasDrawH)
					this.canvasObj.draw()

				}
				if (e.changedTouches.length > 1 && this.TouchstartArr.length > 1) {
					let StartTouchSpotOne = this.TouchstartArr.find(function(item) {
						return item.identifier == e.changedTouches[0].identifier
					})
					let StartTouchSpotTwo = this.TouchstartArr.find(function(item) {
						return item.identifier == e.changedTouches[1].identifier
					})

					if (StartTouchSpotOne && StartTouchSpotTwo) {
						let startL = Math.pow((StartTouchSpotOne.x - StartTouchSpotTwo.x), 2) + Math.pow((
							StartTouchSpotOne.y - StartTouchSpotTwo.y), 2)

						let endL = Math.pow((e.changedTouches[0].x - e.changedTouches[1].x), 2) + Math.pow((
							e.changedTouches[0].y - e.changedTouches[1].y), 2)


						// 判断两个触点之间的相对距离
						if (startL - endL > 0) { //缩小
							let newImageDrawW = this.imageDrawInfo.imageDrawW * 1.02
							let newImageDrawH = this.imageDrawInfo.imageDrawH * 1.02
							if (newImageDrawH < this.imageDrawInfo.beginningImageDrawH && newImageDrawW < this
								.imageDrawInfo.beginningImageDrawW) {


								// 赋值开始图片区域（到达右侧 下方的判定）
								if (this.imageDrawInfo.imageX >= this.imageW - this.imageDrawInfo.imageDrawW) {
									this.imageDrawInfo.imageX = this.imageW - newImageDrawW
								}
								if (this.imageDrawInfo.imageY >= this.imageH - this.imageDrawInfo.imageDrawH) {
									this.imageDrawInfo.imageY = this.imageH - newImageDrawH
								}

								// 赋值绘制区域
								this.imageDrawInfo.imageDrawW = newImageDrawW
								this.imageDrawInfo.imageDrawH = newImageDrawH
								this.canvasObj.drawImage(this.srcCopy, this.imageDrawInfo.imageX, this.imageDrawInfo
									.imageY,
									this
									.imageDrawInfo.imageDrawW, this.imageDrawInfo.imageDrawH, 0, 0, this
									.imageDrawInfo
									.canvasDrawW,
									this.imageDrawInfo
									.canvasDrawH)
								this.canvasObj.draw()
							}

						} else { //放大
							this.imageDrawInfo.imageDrawW = this.imageDrawInfo.imageDrawW / 1.02
							this.imageDrawInfo.imageDrawH = this.imageDrawInfo.imageDrawH / 1.02
							this.canvasObj.drawImage(this.srcCopy, this.imageDrawInfo.imageX, this.imageDrawInfo
								.imageY,
								this
								.imageDrawInfo.imageDrawW, this.imageDrawInfo.imageDrawH, 0, 0, this
								.imageDrawInfo
								.canvasDrawW, this.imageDrawInfo.canvasDrawH)
							this.canvasObj.draw()
						}
					}


				}
			},
			// 触摸结束
			canvasTouchend(e) {
				this.TouchstartArr = this.TouchstartArr.filter(function(item) {
					item.identifier != e.identifier
				})
			},
			getId() {
				let id = this._id + "canvas"
				for (let i = 0; i < 3; i++) {
					id += Math.ceil(Math.random() * 100).toString()
				}
				return id
			},
			drewImage() {
				let that = this
				if (!this.canvasObj) {
					this.canvasObj = uni.createCanvasContext(this.id, this)
				}
				let context = this.canvasObj
				context.clearRect(0, 0, this.canvasW, this.canvasH)
				context.draw()
				uni.getImageInfo({
					src: this.srcCopy,
					success(e) {
						that.imageH = e.height
						that.imageW = e.width
						// 计算图片的绘制区域
						that.imageDrawInfo.imageDrawW = e.width
						that.imageDrawInfo.imageDrawH = Math.round(that.canvasH / that.canvasW * e.width)
						if (that.imageDrawInfo.imageDrawH > that.imageH) {
							that.imageDrawInfo.imageDrawH = e.height
							that.imageDrawInfo.imageDrawW = Math.round(that.canvasW / that.canvasH * e
								.height)
						}
						that.imageDrawInfo.beginningImageDrawW = that.imageDrawInfo.imageDrawW
						that.imageDrawInfo.beginningImageDrawH = that.imageDrawInfo.imageDrawH
						// 计算图片的绘制起点
						that.imageDrawInfo.imageX = (e.width - that.imageDrawInfo.imageDrawW) / 2
						that.imageDrawInfo.imageY = (e.height - that.imageDrawInfo.imageDrawH) / 2
						that.imageDrawInfo.beginningImageX = (e.width - that.imageDrawInfo.imageDrawW) / 2
						that.imageDrawInfo.beginningImageY = (e.height - that.imageDrawInfo.imageDrawH) / 2
						context.drawImage(that.srcCopy, that.imageDrawInfo.imageX, that.imageDrawInfo
							.imageY, that
							.imageDrawInfo.imageDrawW, that.imageDrawInfo.imageDrawH, 0, 0, that
							.imageDrawInfo
							.canvasDrawW,
							that.imageDrawInfo
							.canvasDrawH)
						context.draw()
					}
				})





			},
			imageClick() {
				// this.previewImage()
				if (this.isCut && this.type == "image") {
					this.isShowCutArea = true
					this.computeCanvasWH()
					setTimeout(() => {
						this.drewImage()
					}, 500)

				} else {
					this.previewImage()
				}
			},

			previewImage() {
				uni.previewImage({
					urls: [this.src]
				})
			},

			// 压缩图片
			compressImage(tempFilePaths) {
				return new Promise((a, b) => {
					uni.compressImage({
						src: tempFilePaths,
						quality: this.quality,
						width: "50%",
						height: "50%",
						success(e) {
							a(e)
						},
						fail(e) {
							b()
						}
					})
				})
			},
			uploadFile() {
				if (this.type == "image") {
					this.addImage()
				} else if (this.type == "video") {
					this.addVideo()
				}
			},

			deleteFn() {
				this.$emit("deleteFn", this.addition)
			},
			// 上传视频
			addVideo() {
				const self = this;
				uni.chooseVideo({
					count: 1,
					success: async (res) => {
						uni.showLoading({
							title: "上传中"
						})
						let result = []
						const tempFilePaths = res.tempFilePath
						try {
							let xhr = await updateFile(tempFilePaths)
							if (xhr.success) {
								result.push(xhr.url)
								if (!self.srcCopy && self.isShowFile) {
									self.srcCopy = xhr.url
								}
								self.$emit("succeed", {
									url: xhr.url,
									addition: self.addition
								})
							} else {
								uni.showToast({
									title: "上传失败",
									icon: "none"
								})
								uni.hideLoading()
							}
						} catch (e) {}
						uni.hideLoading()
						self.$emit("succeedAll", {
							urls: result,
							addition: self.addition
						})
					},
				})
			},
			//  上传图片
			addImage() {
				const self = this;
				uni.chooseImage({
					count: this.multiNumber <= 9 ? this.multiNumber : 9, //默认9
					sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图，默认二者都有
					sourceType: ['album', "camera"], // 可以指定来源是相册还是相机，默认二者都有
					success: async (res) => {
						uni.showLoading({
							title: "上传中"
						})
						let result = []
						for (let i = 0; i < res.tempFilePaths.length; i++) {
							const tempFilePaths = res.tempFilePaths[i]
							if (self.isCompress) {
								try {
									let tempFilePaths = await self.compressImage(tempFilePaths)
								} catch (e) {

								}
							}
							try {
								let xhr = await updateFile(tempFilePaths)
								if (xhr.success) {
									result.push(xhr.url)
									if (!self.srcCopy && self.isShowFile) {
										self.srcCopy = xhr.url
									}
									self.$emit("succeed", {
										url: xhr.url,
										addition: self.addition
									})
								} else {
									uni.showToast({
										title: "上传失败",
										icon: "none"
									})
									uni.hideLoading()
								}
							} catch (e) {
								console.error("上传失败")
							}
						}
						uni.hideLoading()
						self.$emit("succeedAll", {
							result,
							addition: self.addition
						})
					},
					fail() {

					}
				});
			},
			// 计算canvas的宽高
			computeCanvasWH() {

				console.log(this.sysInfo, "2323")
				let canvasW = this.sysInfo.screenWidth * 0.8
				let canvasH = (canvasW / this.width) * this.height
				if (canvasH > this.sysInfo.screenHeight * 0.8) {
					canvasH = this.sysInfo.screenHeight * 0.8
					canvasW = (canvasH / this.height) * this.width
				}
				this.canvasW = canvasW
				this.canvasH = canvasH
				this.imageDrawInfo.canvasDrawW = canvasW
				this.imageDrawInfo.canvasDrawH = canvasH
				this.canvasStyle = {
					width: canvasW + "px",
					height: canvasH + "px",
				}

			},
		},
		created() {
			this.id = this.getId()
			this.sysInfo = uni.getSystemInfoSync()
			this.srcCopy = this.src
			this.boxStyle = {
				width: this.width + "rpx",
				height: this.height + "rpx"
			}
			this.addIMageStyle = {
				width: this.addIconSize + "rpx",
				// height: this.addIconSize + "rpx",
			}

		}
	}
</script>

<style scoped lang="less">
	.affirm {
		width: 112rpx;
		height: 46rpx;
		position: absolute;
		line-height: 46rpx;
		top: 90%;
		right: 150rpx;
		font-size: 30rpx;
		background-color: #FFFFFF;
		z-index: 10000;
		border-radius: 10rpx;
		background: #3558B9;
		text-align: center;
		color: #FFFFFF;
	}

	.cancal {
		width: 112rpx;
		height: 46rpx;
		line-height: 46rpx;
		position: absolute;
		top: 90%;
		left: 150rpx;
		font-size: 30rpx;
		background-color: #FFFFFF;
		z-index: 10000;
		border-radius: 10rpx;
		text-align: center;
	}

	.canvas {
		// background-color: #FFFFFF;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translateX(-50%) translateY(-50%);
		border: solid #000000 1rpx;
	}

	.CutBox {
		background-color: rgba(0, 0, 0, 0.8);
		position: fixed;
		z-index: 10000;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
	}

	.upload_File {
		position: relative;

		.remove {
			position: absolute;
			width: 70rpx;
			top: 0;
			right: 0;
			z-index: 2;
		}

		.ckeckIcon {
			top: 0rpx;
			left: 0rpx;
			z-index: 2;
			position: absolute;
			width: 40rpx;
			height: 40rpx;
			border-radius: 50%;

			image {
				display: block;
			}
		}

		.removeVideo {
			position: absolute;
			width: 70rpx;
			top: 0;
			right: 0;
			z-index: 2;
			height: 70rpx;
		}
	}

	.default {

		box-shadow: 3rpx 3rpx 10rpx 0rpx rgba(102, 102, 102, 0.07);
		border-radius: 10rpx;
		background: #FAFAFA;
	}

	.addIMageDefault {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%) translateY(-50%);
	}

	.addIMageIconAndText {
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translateX(-50%) translateY(-50%);
	}

	.hint {
		font-size: 20rpx;
		font-weight: 400;
		color: #666666;
		line-height: 28rpx;
		position: absolute;
		bottom: 0;
		left: 0;
	}

	.image {
		width: 100% !important;
		height: 100% !important;
	}
</style>
